package com.ajavaer.framework.generator.model;

import com.ajavaer.framework.common.tools.StringTools;
import com.ajavaer.framework.common.validate.Validation;
import com.ajavaer.framework.generator.type.JpaNamingType;
import org.hibernate.cfg.ImprovedNamingStrategy;

public class ClassField {
    private String columnName;
    private String fieldName;
    private String fieldType;
    private String dbType;
    private String fieldComment;
    private Boolean notNull;
    private String defaultValue;
    private Integer length;
    private Integer precision;
    private Boolean hasLob = false;
    private Boolean hasDecimal = false;
    private Boolean hasDate = false;
    private Boolean hasDateTime = false;
    private Boolean hasTimestamp = false;
    private Boolean hasCheckfield = false;
    /**
     * 字段命名规则,默认驼峰.
     */
    private JpaNamingType jpaNamingType = JpaNamingType.hump;

    public ClassField() {
    }

    public ClassField(String fieldName, String dbType, String fieldComment, String defaultValue) {
        this(JpaNamingType.hump, fieldName, dbType, fieldComment, false, defaultValue);
    }

    public ClassField(String fieldName, String dbType, String fieldComment) {
        this(JpaNamingType.hump, fieldName, dbType, fieldComment, false, null);
    }


    public ClassField(JpaNamingType fieldNamingType, String fieldName, String dbType, String fieldComment, Boolean notNull, String defaultValue) {
        this.fieldName = fieldName;
        this.jpaNamingType = fieldNamingType;
        this.dbType = dbType.toUpperCase();
        this.fieldComment = fieldComment;
        this.notNull = notNull;
        this.defaultValue = defaultValue;
        process();
    }

    public void process() {
        String[] dbTypeTempArr = this.dbType.replaceAll("\\)| +", "").split("\\(");
        this.dbType = dbTypeTempArr[0];
        if (notNull) {
            this.hasCheckfield = true;
        }
        if (dbTypeTempArr.length == 2) {
            if (dbTypeTempArr[1].contains(",")) {
                String[] dbTypeLength = dbTypeTempArr[1].split(",");
                this.length = Integer.valueOf(dbTypeLength[0]);
                this.precision = Integer.valueOf(dbTypeLength[1]);
            } else {
                this.length = Integer.valueOf(dbTypeTempArr[1]);
            }
        }
        if (this.jpaNamingType == JpaNamingType.hump) {
            if (StringTools.isNotBlank(this.fieldName) && StringTools.isBlank(this.columnName)) {
                this.columnName = ImprovedNamingStrategy.INSTANCE.propertyToColumnName(this.fieldName);
            } else if (StringTools.isNotBlank(this.columnName) && StringTools.isBlank(this.fieldName)) {
                this.fieldName = StringTools.underlineToHump(this.columnName, false);
            }
        } else {
            if (StringTools.isNotBlank(this.fieldName) && StringTools.isBlank(this.columnName)) {
                this.columnName = this.fieldName;
            } else if (StringTools.isNotBlank(this.columnName) && StringTools.isBlank(this.fieldName)) {
                this.fieldName = this.columnName;
            }
        }
        String caseDbType = this.dbType.toUpperCase();
        switch (caseDbType) {
            case "VARCHAR":
            case "CHAR":
            case "TEXT":
            case "LONGTEXT":
                this.fieldType = "String";
                if ("TEXT|LONGTEXT".contains(caseDbType)) {
                    this.hasLob = true;
                }
                break;
            case "INT":
            case "TINYINT":
                this.fieldType = "Integer";
                break;
            case "BIGINT":
                this.fieldType = "Long";
                break;
            case "BIT":
                this.fieldType = "Boolean";
                this.length = 1;
                break;
            case "FLOAT":
                this.fieldType = "Float";
                break;
            case "DOUBLE":
                this.fieldType = "Double";
                break;
            case "DECIMAL":
                this.fieldType = "BigDecimal";
                this.hasDecimal = true;
                break;
            case "DATE":
                this.fieldType = "LocalDate";
                this.hasDate = true;
                break;
            case "DATETIME":
                this.fieldType = "LocalDateTime";
                this.hasDateTime = true;
                break;
            case "TIMESTAMP":
                this.fieldType = "Timestamp";
                this.hasTimestamp = true;
                break;
            default:
                throw Validation.error("不支持该数据类型:" + this.dbType);
        }
    }

    public Boolean getHasDate() {
        return hasDate;
    }

    public void setHasDate(Boolean hasDate) {
        this.hasDate = hasDate;
    }

    public Boolean getHasDateTime() {
        return hasDateTime;
    }

    public void setHasDateTime(Boolean hasDateTime) {
        this.hasDateTime = hasDateTime;
    }

    public Boolean getHasTimestamp() {
        return hasTimestamp;
    }

    public void setHasTimestamp(Boolean hasTimestamp) {
        this.hasTimestamp = hasTimestamp;
    }

    public Boolean getHasDecimal() {
        return hasDecimal;
    }

    public void setHasDecimal(Boolean hasDecimal) {
        this.hasDecimal = hasDecimal;
    }

    public Boolean getHasLob() {
        return hasLob;
    }

    public void setHasLob(Boolean hasLob) {
        this.hasLob = hasLob;
    }

    public String getFieldName() {
        return fieldName;
    }

    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    public String getFieldType() {
        return fieldType;
    }

    public void setFieldType(String fieldType) {
        this.fieldType = fieldType;
    }

    public String getFieldComment() {
        return fieldComment;
    }

    public void setFieldComment(String fieldComment) {
        this.fieldComment = fieldComment;
    }

    public Boolean getNotNull() {
        return notNull;
    }

    public void setNotNull(Boolean notNull) {
        this.notNull = notNull;
    }

    public String getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(String defaultValue) {
        this.defaultValue = defaultValue;
    }

    public Integer getLength() {
        return length;
    }

    public void setLength(Integer length) {
        this.length = length;
    }

    public Integer getPrecision() {
        return precision;
    }

    public void setPrecision(Integer precision) {
        this.precision = precision;
    }

    public String getDbType() {
        return dbType;
    }

    public void setDbType(String dbType) {
        this.dbType = dbType;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    public JpaNamingType getJpaNamingType() {
        return jpaNamingType;
    }

    public void setJpaNamingType(JpaNamingType jpaNamingType) {
        this.jpaNamingType = jpaNamingType;
    }

    public Boolean getHasCheckfield() {
        return hasCheckfield;
    }

    public void setHasCheckfield(Boolean hasCheckfield) {
        this.hasCheckfield = hasCheckfield;
    }
}
